package co.fitstart.coach.web.interceptor;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import org.springframework.web.util.WebUtils;

import com.demo2do.core.cache.handler.CacheHandler;

import co.fitstart.coach.entity.security.Login;
import co.fitstart.coach.service.PrincipalService;
import co.fitstart.entity.principal.Principal;

/**
 * 
 * @author mohanlan
 *
 */
public class AutoLoginInterceptor extends HandlerInterceptorAdapter {
    
    private static final Logger logger = LoggerFactory.getLogger(AutoLoginInterceptor.class);
    
    private String openidKey;
    
    @Autowired
    private CacheHandler coachCacheHandler;
    
    @Autowired
    private PrincipalService principalService;
    
    /**
     * @param openidKey the openidKey to set
     */
    public void setOpenidKey(String openidKey) {
        this.openidKey = openidKey;
    }
    
    /*
     * (non-Javadoc)
     * @see org.springframework.web.servlet.handler.HandlerInterceptorAdapter#preHandle(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, java.lang.Object)
     */
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        
        if (handler instanceof HandlerMethod) {
            
            HandlerMethod handlerMethod = (HandlerMethod) handler;

            // check @AutoLogin annotation
            if(this.checkAutoLogin(handlerMethod)) {
                return super.preHandle(request, response, handlerMethod);
            }
       
            // get userid from cookie
            String userid = this.getUserId(request);
            
            logger.trace("AutologinInterceptor#preHandler() - auto login get userid [{}]", userid);
            
            if(StringUtils.isNotBlank(userid)) {
                
                // get login info from cache
                Login login = coachCacheHandler.get(userid, Login.class);
                
                // if login not exit, get login from database
                if(login == null) {
                    
                    Principal principal = principalService.getPrincipal(userid);
                    
                    if(principal != null) {
                        
                        logger.trace("AutologinInterceptor#preHandler() - auto login success, begin create new login & set Login into cache");
                        
                        // add principal id into cache
                        coachCacheHandler.put(userid, new Login(principal));
                        
                        return super.preHandle(request, response, handlerMethod);
                    }
                    
                    // send to error page when principal can not login into this system
                    logger.trace("AutologinInterceptor#preHandler() - this user with userid[" + userid + "] could not login into the system.");
                    
                    response.sendRedirect(request.getContextPath() + "/auto-login-error");
                    
                    return false;
                    
                } 
                
            } else {
                
                // send to error page when principal can not login into this system
                logger.trace("AutologinInterceptor#preHandler() - we do not get userid from cookie.");
                
                response.sendRedirect(request.getContextPath() + "/auto-login-error");
                
                return false;

            }
            
        }
        
        return super.preHandle(request, response, handler);
    }
    
    /**
     * check AutoLogin annotation
     * 
     * @param handlerMethod
     */
    private boolean checkAutoLogin(HandlerMethod handlerMethod) {
        
        // Find @AutoLogin annotation on handler method
        AutoLogin autoLogin = AnnotationUtils.findAnnotation(handlerMethod.getMethod(), AutoLogin.class);
        
        return autoLogin != null && autoLogin.ignore();
        
    }
    
    /**
     * get user id from cookie
     * 
     * @param request
     * @return
     */
    private String getUserId(HttpServletRequest request) {
        
        Cookie cookie = WebUtils.getCookie(request, this.openidKey);
        
        if(cookie != null) {
            return cookie.getValue();
        }
        
        return null;
    }
}
